﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Hook.Graphics;
using Hook.Graphics.SpriteSheets;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Hook.Environmental.Props
{
    public class Player : Prop
    {
        public const float JUMPACCEL = 20;
        public const float TURNACCEL = 3;
        public const float MOVEACCEL = 1;
        public const float RUNACCEL = 2;
        public const float COASTACCEL = 2;
        public const float LATFALLACCEL = 1;
        public const float TIMETILRUN = 2;

        public const float MAXMOVEVEL = 8;
        public const float MAXRUNVEL = 12;
        public const float MAXLATFALLVEL = 12;

        public const int GROUNDED = 0;
        public const int JUMPING = 1;
        public const int FALLING = 2;

        public const int IDLE = 0;
        public const int MOVING = 1;
        public const int RUNNING = 2;
        public const int TURNING = 3;

        public int BankedStretchJoints;
        public int AerialState, MovementState;
        public double MoveLeftTime, MoveRightTime;
        public bool MovingLeft, MovingRight, LastDirection;

        public Sprite IdleSprite, RunSprite, WalkSprite, JumpSprite, FallSprite;

        public Player()
            : base()
        {
            Sprite = new Sprite(Game1.PropSheet, PropSheet.PLAYER);
            Sprite.FrameRate = 2;

            AerialState = FALLING;
            MovementState = IDLE;

            List<Vector3> VO = new List<Vector3>();

            // Rectangular hitbox
            /*VO.Add(new Vector3(20, 30, 0));
            VO.Add(new Vector3(-20, 30, 0));
            VO.Add(new Vector3(-20, -30, 0));
            VO.Add(new Vector3(20, -30, 0));*/

            // Hexagonal hitbox
            /*VO.Add(new Vector3(20, 20, 0));
            VO.Add(new Vector3(0, 30, 0));
            VO.Add(new Vector3(-20, 20, 0));
            VO.Add(new Vector3(-20, -20, 0));
            VO.Add(new Vector3(0, -30, 0));
            VO.Add(new Vector3(20, -20, 0));*/

            // Triangular hitbox
            VO.Add(new Vector3(-15, -20, 0));
            VO.Add(new Vector3(15, -20, 0));
            VO.Add(new Vector3(0, 30, 0));

            IdleSprite = new Sprite("PlayerIdle.txt");
            RunSprite = new Sprite("PlayerRun.txt");
            WalkSprite = new Sprite("PlayerWalk.txt");
            JumpSprite = new Sprite("PlayerJump.txt");
            FallSprite = new Sprite("PlayerFall.txt");

            Frame.SetPoints(VO);

            //Rotation = new Vector3(0, 0, 0);
            Mass = 20;
            //Inertia = 2000;
            Inertia = float.PositiveInfinity;
            CollisionLayer.Add(0);
            CollisionLayer.Add(3);
            GravityOn = true;

            BankedStretchJoints = 7;

            LoadPropData("Player.txt");
        }

        public bool CanJump()
        {
            if (Grounded)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public void Jump()
        {
            Velocity.Y = 0;
            QueueForce(new Vector3(0, -15 * Mass, 0));
        }

        public void MoveLeft()
        {
            if (Grounded)
            {
                if (Velocity.X < 0)
                {
                    if (MoveLeftTime > TIMETILRUN)
                    {
                        MovementState = RUNNING;
                        Sprite = RunSprite;
                        QueueForce(new Vector3(-RUNACCEL * Mass, 0, 0));
                    }
                    else
                    {
                        MovementState = MOVING;
                        Sprite = WalkSprite;
                        QueueForce(new Vector3(-MOVEACCEL * Mass, 0, 0));
                    }
                }
                else
                {
                    MovementState = TURNING;
                    Sprite = RunSprite;
                    QueueForce(new Vector3(-TURNACCEL * Mass, 0, 0));
                }
            }
            else
            {
                if (Velocity.Y < 0)
                {
                    AerialState = JUMPING;
                }
                else
                {
                    AerialState = FALLING;
                }

                if (Velocity.X < 0)
                {
                    if (MoveLeftTime > TIMETILRUN)
                    {
                        MovementState = RUNNING;
                        QueueForce(new Vector3(-LATFALLACCEL * Mass, 0, 0));
                    }
                    else
                    {
                        MovementState = MOVING;
                        QueueForce(new Vector3(-LATFALLACCEL * Mass, 0, 0));
                    }
                }
                else
                {
                    MovementState = TURNING;
                    QueueForce(new Vector3(-LATFALLACCEL * Mass, 0, 0));
                }

                if (AerialState == JUMPING)
                {
                    Sprite = JumpSprite;
                }
                else if (AerialState == FALLING)
                {
                    Sprite = FallSprite;
                }
            }

            Sprite.SetFlip(true);

            MoveRightTime = 0;
            MovingRight = false;
            MoveLeftTime += .05;
            MovingLeft = true;
            LastDirection = true;
        }
        public void MoveRight()
        {
            if (Grounded)
            {
                if (Velocity.X > 0)
                {
                    if (MoveRightTime > TIMETILRUN)
                    {
                        MovementState = RUNNING;
                        Sprite = RunSprite;
                        QueueForce(new Vector3(RUNACCEL * Mass, 0, 0));
                    }
                    else
                    {
                        MovementState = MOVING;
                        Sprite = WalkSprite;
                        QueueForce(new Vector3(MOVEACCEL * Mass, 0, 0));
                    }
                }
                else
                {
                    MovementState = TURNING;
                    Sprite = RunSprite;
                    QueueForce(new Vector3(TURNACCEL * Mass, 0, 0));
                }
            }
            else
            {
                if (Velocity.Y < 0)
                {
                    AerialState = JUMPING;
                }
                else
                {
                    AerialState = FALLING;
                }

                if (Velocity.X > 0)
                {
                    if (MoveLeftTime > TIMETILRUN)
                    {
                        MovementState = RUNNING;
                        QueueForce(new Vector3(LATFALLACCEL * Mass, 0, 0));
                    }
                    else
                    {
                        MovementState = MOVING;
                        QueueForce(new Vector3(LATFALLACCEL * Mass, 0, 0));
                    }
                }
                else
                {
                    MovementState = TURNING;
                    QueueForce(new Vector3(LATFALLACCEL * Mass, 0, 0));
                }

                if (AerialState == JUMPING)
                {
                    Sprite = JumpSprite;
                }
                else if (AerialState == FALLING)
                {
                    Sprite = FallSprite;
                }
            }

            Sprite.SetFlip(false);

            MoveLeftTime = 0;
            MovingLeft = false;
            MoveRightTime += .05;
            MovingRight = true;
            LastDirection = false;
        }

        public void Coast()
        {
            MovementState = IDLE;
            if (Grounded)
            {
                if (Velocity.X > 0)
                {
                    QueueForce(new Vector3(-COASTACCEL * Mass, 0, 0));
                }
                else if (Velocity.X < 0)
                {
                    QueueForce(new Vector3(COASTACCEL * Mass, 0, 0));
                }

                Sprite = IdleSprite;
            }
            else
            {
                if (Velocity.Y < 0)
                {
                    AerialState = JUMPING;
                }
                else
                {
                    AerialState = FALLING;
                }

                if (AerialState == JUMPING)
                {
                    Sprite = JumpSprite;
                }
                else if (AerialState == FALLING)
                {
                    Sprite = FallSprite;
                }
            }

            /*bool Flip = false;
            if (Sprite.SpriteEffect == SpriteEffects.FlipHorizontally)
                Flip = true;*/
            Sprite.SetFlip(LastDirection);
        }

        public void RestrictVelocity()
        {
            if (MovementState == MOVING)
            {
                if (Math.Abs(Velocity.X) > MAXMOVEVEL)
                {
                    if (Velocity.X < 0)
                    {
                        Velocity.X = -MAXMOVEVEL;
                    }
                    else
                    {
                        Velocity.X = MAXMOVEVEL;
                    }
                }
                Sprite.FrameRate = Math.Abs(Velocity.X) / 1.0f;
            }
            else if (MovementState == RUNNING)
            {
                if (Math.Abs(Velocity.X) > MAXRUNVEL)
                {
                    if (Velocity.X < 0)
                    {
                        Velocity.X = -MAXRUNVEL;
                    }
                    else
                    {
                        Velocity.X = MAXRUNVEL;
                    }
                }
                Sprite.FrameRate = Math.Abs(Velocity.X) / 1.0f;
            }
            else if (MovementState == IDLE && Grounded)
            {
                if (Math.Abs(Velocity.X) < 1.1)
                {
                    Velocity.X = 0;
                }
                Sprite.FrameRate = 2;
            }
        }
    }
}
